package ar.com.algotres.tpdos.modelo.tablero;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import ar.com.algotres.tpdos.modelo.disparos.Disparo;
import ar.com.algotres.tpdos.modelo.disparos.PosicionAExplotarInvalidaExcpetion;
import ar.com.algotres.tpdos.modelo.fisica.CoordenadasDePosicioInvalidaException;
import ar.com.algotres.tpdos.modelo.fisica.Posicion;
import ar.com.algotres.tpdos.modelo.naves.Nave;

public class Tablero {

	private static Tablero singleton;

	public static Tablero getInstance() {
		if (singleton == null) {
			singleton = new Tablero();
		}
		return singleton;
	}

	private Integer dimensionEnX = 10;
	private Integer dimensionEnY = 10;
	private List<Disparo> disparos = new ArrayList<Disparo>();
	private List<Nave> naves = new ArrayList<Nave>();
	private VigilanciaMarina vigilancia;

	private Tablero() {
		vigilancia = new VigilanciaMarina();
	}

	private void activarDisparos() throws PosicionAExplotarInvalidaExcpetion {
		for (Disparo disparo : disparos) {
			disparo.vivir();
		}
	}

	public void actualizarMapa() throws NaveNoInvertibleException,
			PosicionAExplotarInvalidaExcpetion {
		this.activarDisparos();
		this.actualizarNaves();
	}

	private void actualizarNaves() throws NaveNoInvertibleException {
		Iterator<Nave> it = naves.iterator();
		while (it.hasNext()) {
			Nave nave = it.next();
			try {
				nave.vivir();
			} catch (CoordenadasDePosicioInvalidaException e) {
				try {
					nave.invertir();
				} catch (CoordenadasDePosicioInvalidaException e1) {
					throw new NaveNoInvertibleException(e.getMessage());
				}
			}
		}
	}

	public List<Nave> buscarNavesEn(Posicion posicion) {
		List<Nave> barcos = new ArrayList<Nave>();
		Iterator<Nave> it = naves.iterator();
		while (it.hasNext()) {
			Nave nave = it.next();
			if (nave.hayBloqueEnPosicion(posicion))
				barcos.add(nave);
		}
		return barcos;
	}

	public void explosionEn(Posicion posicion, Disparo disparo) {
		List<Nave> naves = this.buscarNavesEn(posicion);
		if (!naves.isEmpty()) {
			for (Nave nave : naves) {
				if (vigilancia.puedeDipararEl(disparo, nave)) {
					nave.explosionEn(posicion);
				}
			}
		}
	}

	public int getDimensionX() {
		return dimensionEnX;
	}

	public int getDimensionY() {
		return dimensionEnY;
	}

	public void ponerDisparo(Disparo disparo) {
		disparos.add(disparo);
	}

	public void ponerNave(Nave nave) {
		naves.add(nave);
	}

	public void resetTablero() {
		singleton.disparos = new ArrayList<Disparo>();
		singleton.naves = new ArrayList<Nave>();
	}
}
